//
// Created by 麻再挺 on 2021/12/16.
//

#include "order_graph.h"

/**
 * 创建有向图
 * @param g 图
 * @param arr 数组
 */
void CreateDG(MGraph *g, const int arr[]);

/**
 * 创建有向网
 * @param g 图
 * @param arrW 数组
 */
void CreateDN(MGraph *g, const int arrW[]);

/**
 * 创建无向图
 * @param g 图
 * @param arr 数组
 */
void CreateUDG(MGraph *g, const int arr[]);

/**
 * 创建无向网
 * @param g 图
 * @param arrW 数组
 */
void CreateUDN(MGraph *g, const int arrW[]);

/**
 * 从图中确定值的位置
 * @param g 图
 * @param v 值
 * @return
 */
int LocateVex(MGraph *g, int v);

/**
 * 创建图
 * @param g 图
 */
void CreateGraph(MGraph *g, int vexNum, int arcNum, int arr[], int arrW[]) {
    printf("请输入创建图的类型(0: 有向图; 1: 有向网; 2: 无向图; 3: 无向网): ");
    // 赋值图类型
    scanf("%d", &g->kind);
    // 赋值图顶点数
    g->vexNum = vexNum;
    // 赋值弧数
    g->arcNum = arcNum;
    // 依次对顶点本身赋值
    for (int i = 0; i < g->vexNum; ++i) {
        g->vex[i] = i + 1;
    }
    // 初始化二维矩阵, 全部归 0, 指针为 NULL
    for (int i = 0; i < g->vexNum; ++i) {
        for (int j = 0; j < g->vexNum; ++j) {
            // 赋值源数据
            g->arcs[i][j].adj = 0;
            // 赋值信息
            g->arcs[i][j].info = NULL;
        }
    }
    // 根据所选类型创建图
    switch (g->kind) {
        case DG:
            CreateDG(g, arr);
            break;
        case DN:
            CreateDN(g, arrW);
            break;
        case UDG:
            CreateUDG(g, arr);
            break;
        case UDN:
            CreateUDN(g, arrW);
            break;
    }


}

void CreateDG(MGraph *g, const int arr[]) {
    // 向二维数组中添加弧的数据
    for (int i = 0; i < g->arcNum; ++i) {
        // 弧头弧尾
        int v1 = arr[2 * i];
        int v2 = arr[2 * i + 1];
        // 确定顶点位置
        int m = LocateVex(g, v1);
        int n = LocateVex(g, v2);
        //排除错误数据
        if (m == -1 || n == -1) {
            printf("no this vertex\n");
            return;
        }
        // 将正确的弧加入二维数组
        g->arcs[m][n].adj = 1;
    }
}

void CreateDN(MGraph *g, const int arrW[]) {
    // 向二维数组中添加弧的数据
    for (int i = 0; i < g->arcNum; ++i) {
        // 弧头弧尾
        int v1 = arrW[3 * i];
        int v2 = arrW[3 * i + 1];
        int w = arrW[3 * i + 2];
        // 确定顶点位置
        int m = LocateVex(g, v1);
        int n = LocateVex(g, v2);
        //排除错误数据
        if (m == -1 || n == -1) {
            printf("no this vertex\n");
            return;
        }
        // 将正确的弧加入二维数组
        g->arcs[m][n].adj = w;
    }
}

void CreateUDG(MGraph *g, const int arr[]) {
    // 向二维数组中添加弧的数据
    for (int i = 0; i < g->arcNum; ++i) {
        // 弧头弧尾
        int v1 = arr[2 * i];
        int v2 = arr[2 * i + 1];
        // 确定顶点位置
        int m = LocateVex(g, v1);
        int n = LocateVex(g, v2);
        //排除错误数据
        if (m == -1 || n == -1) {
            printf("no this vertex\n");
            return;
        }
        // 将正确的弧加入二维数组, 没有方向将反向也设置为 1
        g->arcs[m][n].adj = 1;
        g->arcs[n][m].adj = 1;
    }
}

void CreateUDN(MGraph *g, const int arrW[]) {
    // 向二维数组中添加弧的数据
    for (int i = 0; i < g->arcNum; ++i) {
        // 弧头弧尾
        int v1 = arrW[3 * i];
        int v2 = arrW[3 * i + 1];
        int w = arrW[3 * i + 2];
        // 确定顶点位置
        int m = LocateVex(g, v1);
        int n = LocateVex(g, v2);
        //排除错误数据
        if (m == -1 || n == -1) {
            printf("no this vertex\n");
            return;
        }
        // 将正确的弧加入二维数组
        g->arcs[m][n].adj = w;
        g->arcs[n][m].adj = w;
    }
}

int LocateVex(MGraph *g, int v) {
    int i = 0;
    for (; i < g->vexNum; ++i) {
        if (g->vex[i] == v) {
            break;
        }
    }
    // 找不到的情况
    if (i > g->vexNum) {
        printf("no such vertex.\n");
        return -1;
    }
    return i;
}

/**
 * 打印图
 * @param g 图
 */
void PrintGraph(MGraph g) {
    for (int i = 0; i < g.vexNum; i++) {
        for (int j = 0; j < g.vexNum; j++) {
            int num = g.arcs[i][j].adj;
            if (num == 0) {
                printf("%s ", "∞");
            } else {
                printf("%d ", num);
            }
        }
        printf("\n");
    }
}




